<commit_before>/*
Copyright (c) 2012 Carsten Burstedde, Donna Calhoun
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.

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 HOLDER 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.
*/

/** \file fclaw2d_face_neighbors.cpp
 * Average, coarsen and copy between grids at faces.
 **/

#include <fclaw2d_global.h>

#include <fclaw2d_ghost_fill.h>
#include <fclaw2d_clawpatch.hpp>
#include <ClawPatch.H>

/* This is used to determine neighbor patch relative level (finer, coarser or samesize) */
enum
{
    COARSER_GRID = -1,
    SAMESIZE_GRID,
    FINER_GRID
};

/* This function is a bit overkill, but I put it here so the logic in both
   the corner fill and face fill are the same */
static
void get_face_type(fclaw2d_domain_t *domain,
                   int iface,
                   fclaw_bool intersects_phys_bdry[],
                   fclaw_bool intersects_block[],
                   fclaw_bool *is_block_face,
                   fclaw_bool *is_interior_face)
{
    *is_block_face = intersects_block[iface];
    *is_interior_face = !intersects_phys_bdry[iface];
}

static
void get_face_neighbors(fclaw2d_domain_t *domain,
                        int this_block_idx,
                        int this_patch_idx,
                        int iface,
                        int is_block_face,
                        int *neighbor_block_idx,
                        fclaw2d_patch_t* neighbor_patches[],
                        int **ref_flag_ptr,
                        int **fine_grid_pos_ptr,
                        int **iface_neighbor_ptr,
                        int ftransform[],
                        fclaw2d_transform_data_t* ftransform_finegrid)
{
    int rproc[p4est_refineFactor];
    int rblockno;
    int rpatchno[p4est_refineFactor];
    int rfaceno;
    int num_neighbors;

    for(int ir = 0; ir < p4est_refineFactor; ir++)
    {
        neighbor_patches[ir] = NULL;
    }

    fclaw2d_patch_relation_t neighbor_type =
        fclaw2d_patch_face_neighbors(domain,
                                     this_block_idx,
                                     this_patch_idx,
                                     iface,
                                     rproc,
                                     &rblockno,
                                     rpatchno,
                                     &rfaceno);

    /* ------------------------------
      neighbor_type is one of :
      FCLAW2D_PATCH_BOUNDARY,    -- physical boundary
      FCLAW2D_PATCH_HALFSIZE,
      FCLAW2D_PATCH_SAMESIZE,
      FCLAW2D_PATCH_DOUBLESIZE
      ------------------------------- */

    if (neighbor_type == FCLAW2D_PATCH_BOUNDARY)
    {
        /* This case should be excluded by earlier checkes */
        printf("get_face_neighbors (fclaw2d_face_neighbors.cpp) : No patch found\n");
        exit(0);
    }
    else
    {
        *neighbor_block_idx = is_block_face ? rblockno : -1;
        /* Get encoding of transforming a neighbor coordinate across a face */
        fclaw2d_patch_face_transformation (iface, rfaceno, ftransform);

        int iface1, rface1;
        iface1 = iface;
        rface1 = rfaceno;
        fclaw2d_patch_face_swap(&iface1,&rface1);
        fclaw2d_patch_face_transformation (iface1, rface1,
                                           ftransform_finegrid->transform);
        ftransform_finegrid->block_iface = iface1;
        **iface_neighbor_ptr = iface1;

        if (!is_block_face)
        {
            /* If we are within one patch this is a special case */
            FCLAW_ASSERT (*neighbor_block_idx == -1);
            ftransform[8] = 4;
            ftransform_finegrid->transform[8] = 4;
        }

        if (neighbor_type == FCLAW2D_PATCH_SAMESIZE)
        {
            **ref_flag_ptr = 0;
            *fine_grid_pos_ptr = NULL;
            num_neighbors = 1;
        }
        else if (neighbor_type == FCLAW2D_PATCH_DOUBLESIZE)
        {
            **ref_flag_ptr = -1;
            **fine_grid_pos_ptr = rproc[1];    /* Special storage for fine grid info */
            num_neighbors = 1;
        }
        else if (neighbor_type == FCLAW2D_PATCH_HALFSIZE)
        {
            /* Patch has two neighbors */
            **ref_flag_ptr = 1; /* patches are at one level finer */
            *fine_grid_pos_ptr = NULL;
            num_neighbors = p4est_refineFactor;
        }
        else
        {
            printf ("Illegal fclaw2d_patch_face_neighbors return value\n");
            exit (1);
        }

        for(int ir = 0; ir < num_neighbors; ir++)
        {
            fclaw2d_patch_t *neighbor;
            if (rproc[ir] == domain->mpirank)
            {
                /* neighbor patch is local */
                fclaw2d_block_t *neighbor_block = &domain->blocks[rblockno];
                neighbor = &neighbor_block->patches[rpatchno[ir]];
            }
            else
            {
                /* neighbor patch is on a remote processor */
                neighbor = &domain->ghost_patches[rpatchno[ir]];
            }
            neighbor_patches[ir] = neighbor;
        }
    }
}

/**
 * \ingroup Averaging
 **/
void cb_face_fill(fclaw2d_domain_t *domain,
                  fclaw2d_patch_t *this_patch,
                  int this_block_idx,
                  int this_patch_idx,
                  void *user)
{
    fclaw2d_exchange_info_t *filltype = (fclaw2d_exchange_info_t*) user;
    fclaw_bool time_interp = filltype->time_interp;
    fclaw_bool is_coarse = filltype->grid_type == FCLAW2D_IS_COARSE;
    fclaw_bool is_fine = filltype->grid_type == FCLAW2D_IS_FINE;

    fclaw_bool read_parallel_patches = filltype->read_parallel_patches;

    fclaw_bool copy_from_neighbor = filltype->exchange_type == FCLAW2D_COPY;
    fclaw_bool average_from_neighbor = filltype->exchange_type == FCLAW2D_AVERAGE;
    fclaw_bool interpolate_to_neighbor = filltype->exchange_type == FCLAW2D_INTERPOLATE;

    const amr_options_t *gparms = get_domain_parms(domain);
    const int refratio = gparms->refratio;

    fclaw_bool intersects_phys_bdry[NumFaces];
    fclaw_bool intersects_block[NumFaces];

    fclaw2d_get_physical_bc(domain,this_block_idx,this_patch_idx,
                            intersects_phys_bdry);

    fclaw2d_block_get_block_boundary(domain, this_patch, intersects_block);

    /* Transform data needed at block boundaries */
    fclaw2d_transform_data_t transform_data;
    transform_data.mx = gparms->mx;
    transform_data.my = gparms->my;
    transform_data.based = 1;                 /* cell-centered data in this routine. */
    transform_data.this_patch = this_patch;
    transform_data.neighbor_patch = NULL;     /* gets filled in below. */

    fclaw2d_transform_data_t transform_data_finegrid;
    transform_data_finegrid.mx = gparms->mx;
    transform_data_finegrid.my = gparms->my;
    transform_data_finegrid.based = 1;   /* cell-centered data in this routine. */

    ClawPatch *this_cp = fclaw2d_clawpatch_get_cp(this_patch);
    for (int iface = 0; iface < NumFaces; iface++)
    {
        int idir = iface/2;

        fclaw_bool is_block_face;
        fclaw_bool is_interior_face;
        get_face_type(domain,
                      iface,
                      intersects_phys_bdry,
                      intersects_block,
                      &is_block_face,
                      &is_interior_face);

        if (is_interior_face)  /* Not on a physical boundary */
        {
            /* Output arguments */
            int neighbor_block_idx;
            int neighbor_level;   /* = -1, 0, 1 */
            int *ref_flag_ptr = &neighbor_level;
            int fine_grid_pos = -1;
            int *fine_grid_pos_ptr = &fine_grid_pos;

            /* Get the face neighbor relative to the neighbor's coordinate
               orientation (this isn't used here) */
            int iface_neighbor;
            int *iface_neighbor_ptr = &iface_neighbor;

            fclaw2d_patch_t* neighbor_patches[p4est_refineFactor];

            /* Reset this in case it got set in a remote copy */
            transform_data.this_patch = this_patch;
            this_cp = fclaw2d_clawpatch_get_cp(this_patch);

            transform_data_finegrid.block_iface = -1;

            /* transform_data.block_iface = iface; */
            get_face_neighbors(domain,
                               this_block_idx,
                               this_patch_idx,
                               iface,
			       is_block_face,
                               &neighbor_block_idx,
                               neighbor_patches,
                               &ref_flag_ptr,
                               &fine_grid_pos_ptr,
                               &iface_neighbor_ptr,
                               transform_data.transform,
                               &transform_data_finegrid);

            /* Needed for switching the context */
            transform_data_finegrid.this_patch = neighbor_patches[0];
            transform_data_finegrid.neighbor_patch = this_patch;

            /* fclaw_bool block_boundary = (neighbor_block_idx >= 0); */
            if (ref_flag_ptr == NULL)
            {
                /* We should never end up here */
                printf("cb_face_fill (fclaw2d_face_neighbors.cpp) : no face found\n");
                exit(0);
            }

            /* Parallel distribution keeps siblings on same processor */
            fclaw_bool remote_neighbor;
            remote_neighbor = fclaw2d_patch_is_ghost(neighbor_patches[0]);
            if (is_coarse)
            {
                if (neighbor_level == FINER_GRID)
                {
                    for (int igrid = 0; igrid < p4est_refineFactor; igrid++)
                    {
                        remote_neighbor = fclaw2d_patch_is_ghost(neighbor_patches[igrid]);
                        if (!((read_parallel_patches && remote_neighbor) || !remote_neighbor))
                        {
                            continue;
                        }
                        ClawPatch *fine_neighbor_cp =
                            fclaw2d_clawpatch_get_cp(neighbor_patches[igrid]);
                        transform_data.neighbor_patch = neighbor_patches[igrid];
                        if (interpolate_to_neighbor && !remote_neighbor)
                        {
                            /* interpolate to igrid */
                            this_cp->interpolate_face_ghost(idir,iface,p4est_refineFactor,
                                                            refratio,fine_neighbor_cp,
                                                            time_interp,igrid,
                                                            &transform_data);
                        }
                        else if (average_from_neighbor)
                        {
                            /* average from igrid */
                            this_cp->average_face_ghost(idir,iface,p4est_refineFactor,
                                                        refratio,fine_neighbor_cp,
                                                        time_interp,igrid,
                                                        &transform_data);
                        }
                    }
                }
                else if (neighbor_level == SAMESIZE_GRID && copy_from_neighbor)
                {
                    /* Copy to same size patch */
                    fclaw2d_patch_t *neighbor_patch = neighbor_patches[0];
                    ClawPatch *neighbor_cp = fclaw2d_clawpatch_get_cp(neighbor_patch);
                    transform_data.neighbor_patch = neighbor_patch;
                    this_cp->exchange_face_ghost(iface,neighbor_cp,&transform_data);

                    /* We also need to copy _to_ the remote neighbor; switch contexts, but
                       use ClawPatches that are only in scope here, to avoid
                       conflicts with above uses of the same variables. This is needed
                       in case we want to interpolate to adjacent corners on fine grids.*/
                    if (remote_neighbor)
                    {
                        /* Create a new transform so we don't mess up the original one */
                        ClawPatch *neighbor_cp = this_cp;
                        ClawPatch *this_cp = fclaw2d_clawpatch_get_cp(neighbor_patch);
                        int this_iface = iface_neighbor;
                        this_cp->exchange_face_ghost(this_iface,neighbor_cp,
                                                     &transform_data_finegrid);
                    }
                }
            }
            else if (is_fine && neighbor_level == COARSER_GRID && remote_neighbor
                     && read_parallel_patches)
            {
                int iface_coarse = iface_neighbor;
                int igrid = fine_grid_pos;  /* Not used */
                int idir_coarse = iface_coarse/2;

                /* Swap 'this_patch' (fine grid) and the neighbor patch (a coarse grid) */
                ClawPatch *coarse_cp = fclaw2d_clawpatch_get_cp(neighbor_patches[0]);
                ClawPatch *fine_cp = fclaw2d_clawpatch_get_cp(this_patch);

		if (average_from_neighbor)
                {
		    /* Average from 'this' grid (fine grid) to remote grid (coarse grid) */
		    coarse_cp->average_face_ghost(idir_coarse,iface_coarse,
						  p4est_refineFactor,refratio,
						  fine_cp,time_interp,
						  igrid, &transform_data_finegrid);
                }
                else if (interpolate_to_neighbor)
                {
                    /* Interpolate from remote neighbor to 'this' patch (the finer grid */
                    fedisableexcept(FE_INVALID);
                    coarse_cp->interpolate_face_ghost(idir_coarse,iface_coarse,
                                                      p4est_refineFactor,refratio,
                                                      fine_cp,time_interp,
                                                      igrid, &transform_data_finegrid);
                    if (gparms->trapfpe)
                    {
                        feenableexcept(FE_INVALID);
                    }
                }
            }
        }  /* End of interior face */
    } /* End of iface loop */
}
<commit_msg>Comments<commit_after>/*
Copyright (c) 2012 Carsten Burstedde, Donna Calhoun
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.

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 HOLDER 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.
*/

/** \file fclaw2d_face_neighbors.cpp
 * Average, coarsen and copy between grids at faces.
 **/

#include <fclaw2d_global.h>

#include <fclaw2d_ghost_fill.h>
#include <fclaw2d_clawpatch.hpp>
#include <ClawPatch.H>

/* This is used to determine neighbor patch relative level
   (finer, coarser or samesize) */
enum
{
    COARSER_GRID = -1,
    SAMESIZE_GRID,
    FINER_GRID
};

/* This function is a bit overkill, but I put it here so the logic in both
   the corner fill and face fill are the same */
static
void get_face_type(fclaw2d_domain_t *domain,
                   int iface,
                   fclaw_bool intersects_phys_bdry[],
                   fclaw_bool intersects_block[],
                   fclaw_bool *is_block_face,
                   fclaw_bool *is_interior_face)
{
    *is_block_face = intersects_block[iface];
    *is_interior_face = !intersects_phys_bdry[iface];
}

static
void get_face_neighbors(fclaw2d_domain_t *domain,
                        int this_block_idx,
                        int this_patch_idx,
                        int iface,
                        int is_block_face,
                        int *neighbor_block_idx,
                        fclaw2d_patch_t* neighbor_patches[],
                        int **ref_flag_ptr,
                        int **fine_grid_pos_ptr,
                        int **iface_neighbor_ptr,
                        int ftransform[],
                        fclaw2d_transform_data_t* ftransform_finegrid)
{
    int rproc[p4est_refineFactor];
    int rblockno;
    int rpatchno[p4est_refineFactor];
    int rfaceno;
    int num_neighbors;

    for(int ir = 0; ir < p4est_refineFactor; ir++)
    {
        neighbor_patches[ir] = NULL;
    }

    fclaw2d_patch_relation_t neighbor_type =
        fclaw2d_patch_face_neighbors(domain,
                                     this_block_idx,
                                     this_patch_idx,
                                     iface,
                                     rproc,
                                     &rblockno,
                                     rpatchno,
                                     &rfaceno);

    /* ------------------------------
      neighbor_type is one of :
      FCLAW2D_PATCH_BOUNDARY,    -- physical boundary
      FCLAW2D_PATCH_HALFSIZE,
      FCLAW2D_PATCH_SAMESIZE,
      FCLAW2D_PATCH_DOUBLESIZE
      ------------------------------- */

    if (neighbor_type == FCLAW2D_PATCH_BOUNDARY)
    {
        /* This case should be excluded by earlier checkes */
        printf("get_face_neighbors (fclaw2d_face_neighbors.cpp) : No patch " \
               "found\n");
        exit(0);
    }
    else
    {
        *neighbor_block_idx = is_block_face ? rblockno : -1;
        /* Get encoding of transforming a neighbor coordinate across a face */
        fclaw2d_patch_face_transformation (iface, rfaceno, ftransform);

        int iface1, rface1;
        iface1 = iface;
        rface1 = rfaceno;
        fclaw2d_patch_face_swap(&iface1,&rface1);
        fclaw2d_patch_face_transformation (iface1, rface1,
                                           ftransform_finegrid->transform);
        ftransform_finegrid->block_iface = iface1;
        **iface_neighbor_ptr = iface1;

        if (!is_block_face)
        {
            /* If we are within one patch this is a special case */
            FCLAW_ASSERT (*neighbor_block_idx == -1);
            ftransform[8] = 4;
            ftransform_finegrid->transform[8] = 4;
        }

        if (neighbor_type == FCLAW2D_PATCH_SAMESIZE)
        {
            **ref_flag_ptr = 0;
            *fine_grid_pos_ptr = NULL;
            num_neighbors = 1;
        }
        else if (neighbor_type == FCLAW2D_PATCH_DOUBLESIZE)
        {
            **ref_flag_ptr = -1;
            **fine_grid_pos_ptr = rproc[1];    /* Special storage for fine grid info */
            num_neighbors = 1;
        }
        else if (neighbor_type == FCLAW2D_PATCH_HALFSIZE)
        {
            /* Patch has two neighbors */
            **ref_flag_ptr = 1; /* patches are at one level finer */
            *fine_grid_pos_ptr = NULL;
            num_neighbors = p4est_refineFactor;
        }
        else
        {
            printf ("Illegal fclaw2d_patch_face_neighbors return value\n");
            exit (1);
        }

        for(int ir = 0; ir < num_neighbors; ir++)
        {
            fclaw2d_patch_t *neighbor;
            if (rproc[ir] == domain->mpirank)
            {
                /* neighbor patch is local */
                fclaw2d_block_t *neighbor_block = &domain->blocks[rblockno];
                neighbor = &neighbor_block->patches[rpatchno[ir]];
            }
            else
            {
                /* neighbor patch is on a remote processor */
                neighbor = &domain->ghost_patches[rpatchno[ir]];
            }
            neighbor_patches[ir] = neighbor;
        }
    }
}

/**
 * \ingroup Averaging
 **/
void cb_face_fill(fclaw2d_domain_t *domain,
                  fclaw2d_patch_t *this_patch,
                  int this_block_idx,
                  int this_patch_idx,
                  void *user)
{
    fclaw2d_exchange_info_t *filltype = (fclaw2d_exchange_info_t*) user;
    fclaw_bool time_interp = filltype->time_interp;
    fclaw_bool is_coarse = filltype->grid_type == FCLAW2D_IS_COARSE;
    fclaw_bool is_fine = filltype->grid_type == FCLAW2D_IS_FINE;

    fclaw_bool read_parallel_patches = filltype->read_parallel_patches;

    fclaw_bool copy_from_neighbor = filltype->exchange_type == FCLAW2D_COPY;
    fclaw_bool average_from_neighbor = filltype->exchange_type == FCLAW2D_AVERAGE;
    fclaw_bool interpolate_to_neighbor = filltype->exchange_type == FCLAW2D_INTERPOLATE;

    const amr_options_t *gparms = get_domain_parms(domain);
    const int refratio = gparms->refratio;

    fclaw_bool intersects_phys_bdry[NumFaces];
    fclaw_bool intersects_block[NumFaces];

    fclaw2d_get_physical_bc(domain,this_block_idx,this_patch_idx,
                            intersects_phys_bdry);

    fclaw2d_block_get_block_boundary(domain, this_patch, intersects_block);

    /* Transform data needed at block boundaries */
    fclaw2d_transform_data_t transform_data;
    transform_data.mx = gparms->mx;
    transform_data.my = gparms->my;
    transform_data.based = 1;                 /* cell-centered data in this routine. */
    transform_data.this_patch = this_patch;
    transform_data.neighbor_patch = NULL;     /* gets filled in below. */

    fclaw2d_transform_data_t transform_data_finegrid;
    transform_data_finegrid.mx = gparms->mx;
    transform_data_finegrid.my = gparms->my;
    transform_data_finegrid.based = 1;   /* cell-centered data in this routine. */

    ClawPatch *this_cp = fclaw2d_clawpatch_get_cp(this_patch);
    for (int iface = 0; iface < NumFaces; iface++)
    {
        int idir = iface/2;

        fclaw_bool is_block_face;
        fclaw_bool is_interior_face;
        get_face_type(domain,
                      iface,
                      intersects_phys_bdry,
                      intersects_block,
                      &is_block_face,
                      &is_interior_face);

        if (is_interior_face)  /* Not on a physical boundary */
        {
            /* Output arguments */
            int neighbor_block_idx;
            int neighbor_level;   /* = -1, 0, 1 */
            int *ref_flag_ptr = &neighbor_level;
            int fine_grid_pos = -1;
            int *fine_grid_pos_ptr = &fine_grid_pos;

            /* Get the face neighbor relative to the neighbor's coordinate
               orientation (this isn't used here) */
            int iface_neighbor;
            int *iface_neighbor_ptr = &iface_neighbor;

            fclaw2d_patch_t* neighbor_patches[p4est_refineFactor];

            /* Reset this in case it got set in a remote copy */
            transform_data.this_patch = this_patch;
            this_cp = fclaw2d_clawpatch_get_cp(this_patch);

            transform_data_finegrid.block_iface = -1;

            /* transform_data.block_iface = iface; */
            get_face_neighbors(domain,
                               this_block_idx,
                               this_patch_idx,
                               iface,
			       is_block_face,
                               &neighbor_block_idx,
                               neighbor_patches,
                               &ref_flag_ptr,
                               &fine_grid_pos_ptr,
                               &iface_neighbor_ptr,
                               transform_data.transform,
                               &transform_data_finegrid);

            /* Needed for switching the context */
            transform_data_finegrid.this_patch = neighbor_patches[0];
            transform_data_finegrid.neighbor_patch = this_patch;

            /* fclaw_bool block_boundary = (neighbor_block_idx >= 0); */
            if (ref_flag_ptr == NULL)
            {
                /* We should never end up here */
                printf("cb_face_fill (fclaw2d_face_neighbors.cpp) : no face found\n");
                exit(0);
            }

            /* Parallel distribution keeps siblings on same processor */
            fclaw_bool remote_neighbor;
            remote_neighbor = fclaw2d_patch_is_ghost(neighbor_patches[0]);
            if (is_coarse)
            {
                if (neighbor_level == FINER_GRID)
                {
                    for (int igrid = 0; igrid < p4est_refineFactor; igrid++)
                    {
                        remote_neighbor = fclaw2d_patch_is_ghost(neighbor_patches[igrid]);
                        if (!((read_parallel_patches && remote_neighbor) || !remote_neighbor))
                        {
                            continue;
                        }
                        ClawPatch *fine_neighbor_cp =
                            fclaw2d_clawpatch_get_cp(neighbor_patches[igrid]);
                        transform_data.neighbor_patch = neighbor_patches[igrid];
                        if (interpolate_to_neighbor && !remote_neighbor)
                        {
                            /* interpolate to igrid */
                            this_cp->interpolate_face_ghost(idir,iface,p4est_refineFactor,
                                                            refratio,fine_neighbor_cp,
                                                            time_interp,igrid,
                                                            &transform_data);
                        }
                        else if (average_from_neighbor)
                        {
                            /* average from igrid */
                            this_cp->average_face_ghost(idir,iface,p4est_refineFactor,
                                                        refratio,fine_neighbor_cp,
                                                        time_interp,igrid,
                                                        &transform_data);
                        }
                    }
                }
                else if (neighbor_level == SAMESIZE_GRID && copy_from_neighbor)
                {
                    /* Copy to same size patch */
                    fclaw2d_patch_t *neighbor_patch = neighbor_patches[0];
                    ClawPatch *neighbor_cp = fclaw2d_clawpatch_get_cp(neighbor_patch);
                    transform_data.neighbor_patch = neighbor_patch;
                    this_cp->exchange_face_ghost(iface,neighbor_cp,&transform_data);

                    /* We also need to copy _to_ the remote neighbor; switch contexts, but
                       use ClawPatches that are only in scope here, to avoid
                       conflicts with above uses of the same variables. This is needed
                       in case we want to interpolate to adjacent corners on fine grids.*/
                    if (remote_neighbor)
                    {
                        /* Create a new transform so we don't mess up the original one */
                        ClawPatch *neighbor_cp = this_cp;
                        ClawPatch *this_cp = fclaw2d_clawpatch_get_cp(neighbor_patch);
                        int this_iface = iface_neighbor;
                        this_cp->exchange_face_ghost(this_iface,neighbor_cp,
                                                     &transform_data_finegrid);
                    }
                }
            }
            else if (is_fine && neighbor_level == COARSER_GRID && remote_neighbor
                     && read_parallel_patches)
            {
                int iface_coarse = iface_neighbor;
                int igrid = fine_grid_pos;  /* Not used */
                int idir_coarse = iface_coarse/2;

                /* Swap 'this_patch' (fine grid) and the neighbor patch (a coarse grid) */
                ClawPatch *coarse_cp = fclaw2d_clawpatch_get_cp(neighbor_patches[0]);
                ClawPatch *fine_cp = fclaw2d_clawpatch_get_cp(this_patch);

		if (average_from_neighbor)
                {
		    /* Average from 'this' grid (fine grid) to remote grid (coarse grid) */
		    coarse_cp->average_face_ghost(idir_coarse,iface_coarse,
						  p4est_refineFactor,refratio,
						  fine_cp,time_interp,
						  igrid, &transform_data_finegrid);
                }
                else if (interpolate_to_neighbor)
                {
                    /* Interpolate from remote neighbor to 'this' patch (the finer grid */
                    fedisableexcept(FE_INVALID);
                    coarse_cp->interpolate_face_ghost(idir_coarse,iface_coarse,
                                                      p4est_refineFactor,refratio,
                                                      fine_cp,time_interp,
                                                      igrid, &transform_data_finegrid);
                    if (gparms->trapfpe)
                    {
                        feenableexcept(FE_INVALID);
                    }
                }
            }
        }  /* End of interior face */
    } /* End of iface loop */
}
<|endoftext|>


<commit_before>#/*##########################################################################
#
# The fisx library for X-Ray Fluorescence
#
# Copyright (c) 2020 European Synchrotron Radiation Facility
#
# This file is part of the fisx X-ray developed by V.A. Sole
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
#############################################################################*/
#include <stdexcept>
#include "fisx_transmissiontable.h"
#include <iostream>

namespace fisx
{

TransmissionTable::TransmissionTable()
{
    this->name = "";
    this->comment = "";
    // no attenuation at all
    this->transmissionTable[0.0] = 1.0;
}

TransmissionTable::TransmissionTable(const std::string & name, const std::string & comment)
{
    this->name = name;
    this->comment = comment;
    // no attenuation at all
    this->transmissionTable[0.0] = 1.0;
}

void TransmissionTable::setName(const std::string & name)
{
    this->name = name;
}

void TransmissionTable::setComment(const std::string & comment)
{
    this->comment = comment;
}

void TransmissionTable::setTransmissionTable(const std::map<double, double> & table, \
                          const std::string & name, const std::string & comment)
{
    std::string msg;
        throw std::invalid_argument(msg);
    std::map<double, double>::const_iterator c_it;

    // verify that no value is negative
    for (c_it = table.begin(); c_it != table.end(); ++c_it)
    {
        if (c_it->first < 0.0)
        {
            msg = "TransmissionTable::setTransmissionTable. Invalid energy";
            throw std::invalid_argument(msg);
        }
        if (c_it->second < 0.0)
        {
            msg = "TransmissionTable::setTransmissionTable. Invalid transmission";
            throw std::invalid_argument(msg);
        }
    }

    // verify the table was not already named
    if ((this->name.size() > 0) and (name.size() > 0))
    {
        msg = "TransmissionTable::setTransmissionTable. Table cannot be renamed";
        throw std::invalid_argument(msg);
    }
    if ((this->comment.size() > 0) and (comment.size() > 0))
    {
        msg = "TransmissionTable::setTransmissionTable. Table comment cannot be changed";
        throw std::invalid_argument(msg);
    }

    // assign the values
    this->transmissionTable = table;
    this->name = name;
    this->comment = comment;
}

void TransmissionTable::setTransmissionTable(const std::vector<double> & energy, \
                                             const std::vector<double> & transmission, \
                                             const std::string & name, \
                                             const std::string & comment)
{
    std::vector<double>::size_type i;
    std::string msg;

    // check input
    // verify the table was not already named
    if ((this->name.size() > 0) and (name.size() > 0))
    {
        msg = "TransmissionTable::setTransmissionTable. Table cannot be renamed";
        throw std::invalid_argument(msg);
    }
    if ((this->comment.size() > 0) and (comment.size() > 0))
    {
        msg = "TransmissionTable::setTransmissionTable. Table comment cannot be changed";
        throw std::invalid_argument(msg);
    }

    // verify the data are consistent
    if (energy.size() != transmission.size())
    {
        msg = "TransmissionTable::setTransmissionTable. Number of energies and attenuations not matching";
        throw std::invalid_argument(msg);
    }
    for (i = 0; i < energy.size(); ++i)
    {
        if (energy[i] < 0.0)
        {
            msg = "TransmissionTable::setTransmissionTable. Negative energy";
            throw std::invalid_argument(msg);
        }
        if (transmission[i] < 0.0)
        {
            msg = "TransmissionTable::setTransmissionTable. Negative transmission";
            throw std::invalid_argument(msg);
        }
    }

    // fill the table
    this->transmissionTable.clear();
    for (i = 0; i < energy.size(); ++i)
    {
        this->transmissionTable[energy[i]] = transmission[i];
    }
    this->name = name;
    this->comment = comment;
}

std::string TransmissionTable::getComment() const
{
    return this->comment;
}

std::string TransmissionTable::getName() const
{
    return this->name;
}

double TransmissionTable::getTransmission(const double & energy) const
{
    //typedef std::map<double, double>::const_iterator i_t;
    std::map<double, double>::const_iterator i1, i2;
    double x1, x2, factor;

    if (this->transmissionTable.size() < 1)
    {
        return 1.0;
    }

    if (energy <= 0.0)
    {
        return 1.0;
    }

    i2 = this->transmissionTable.upper_bound(energy);
    if (i2 == this->transmissionTable.end())
    {
        // return last value of the table
        // return (--i)->second;
        // or return 1 because we are dealing with a transmission?
        return 1.0;
    }
    i1 = this->transmissionTable.begin();
    if (energy < (i1->second))
    {
        // return first value of the table
        // return i->second;
        // or return 0 because we are dealing with a transmission?
        return 0.0;
    }
    i1 = i2;
    i1--;

    x1 = i1->first;
    x2 = i2->first;

    // perform a linear interpolation
    factor = (energy - x1) / (x2 - x1);
    return factor * (i2->second) + (1.0 - factor) * i1->second;
}

std::vector<double> TransmissionTable::getTransmission(const std::vector<double> & energy) const
{
    std::vector<double>::size_type n, i;
    std::vector<double> result;

    n = energy.size();
    result.resize(n);
    for (i = 0; i < n; ++i)
    {
        result[i] = this->getTransmission(energy[i]);
    }
    return result;
}

std::map<double, double> TransmissionTable::getTransmissionTable() const
{
    return this->transmissionTable;
}

} // namespace fisx
<commit_msg>Use correct syntax<commit_after>#/*##########################################################################
#
# The fisx library for X-Ray Fluorescence
#
# Copyright (c) 2020 European Synchrotron Radiation Facility
#
# This file is part of the fisx X-ray developed by V.A. Sole
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
#############################################################################*/
#include <stdexcept>
#include "fisx_transmissiontable.h"
#include <iostream>

namespace fisx
{

TransmissionTable::TransmissionTable()
{
    this->name = "";
    this->comment = "";
    // no attenuation at all
    this->transmissionTable[0.0] = 1.0;
}

TransmissionTable::TransmissionTable(const std::string & name, const std::string & comment)
{
    this->name = name;
    this->comment = comment;
    // no attenuation at all
    this->transmissionTable[0.0] = 1.0;
}

void TransmissionTable::setName(const std::string & name)
{
    this->name = name;
}

void TransmissionTable::setComment(const std::string & comment)
{
    this->comment = comment;
}

void TransmissionTable::setTransmissionTable(const std::map<double, double> & table, \
                          const std::string & name, const std::string & comment)
{
    std::string msg;
        throw std::invalid_argument(msg);
    std::map<double, double>::const_iterator c_it;

    // verify that no value is negative
    for (c_it = table.begin(); c_it != table.end(); ++c_it)
    {
        if (c_it->first < 0.0)
        {
            msg = "TransmissionTable::setTransmissionTable. Invalid energy";
            throw std::invalid_argument(msg);
        }
        if (c_it->second < 0.0)
        {
            msg = "TransmissionTable::setTransmissionTable. Invalid transmission";
            throw std::invalid_argument(msg);
        }
    }

    // verify the table was not already named
    if ((this->name.size() > 0) && (name.size() > 0))
    {
        msg = "TransmissionTable::setTransmissionTable. Table cannot be renamed";
        throw std::invalid_argument(msg);
    }
    if ((this->comment.size() > 0) && (comment.size() > 0))
    {
        msg = "TransmissionTable::setTransmissionTable. Table comment cannot be changed";
        throw std::invalid_argument(msg);
    }

    // assign the values
    this->transmissionTable = table;
    this->name = name;
    this->comment = comment;
}

void TransmissionTable::setTransmissionTable(const std::vector<double> & energy, \
                                             const std::vector<double> & transmission, \
                                             const std::string & name, \
                                             const std::string & comment)
{
    std::vector<double>::size_type i;
    std::string msg;

    // check input
    // verify the table was not already named
    if ((this->name.size() > 0) && (name.size() > 0))
    {
        msg = "TransmissionTable::setTransmissionTable. Table cannot be renamed";
        throw std::invalid_argument(msg);
    }
    if ((this->comment.size() > 0) && (comment.size() > 0))
    {
        msg = "TransmissionTable::setTransmissionTable. Table comment cannot be changed";
        throw std::invalid_argument(msg);
    }

    // verify the data are consistent
    if (energy.size() != transmission.size())
    {
        msg = "TransmissionTable::setTransmissionTable. Number of energies and attenuations not matching";
        throw std::invalid_argument(msg);
    }
    for (i = 0; i < energy.size(); ++i)
    {
        if (energy[i] < 0.0)
        {
            msg = "TransmissionTable::setTransmissionTable. Negative energy";
            throw std::invalid_argument(msg);
        }
        if (transmission[i] < 0.0)
        {
            msg = "TransmissionTable::setTransmissionTable. Negative transmission";
            throw std::invalid_argument(msg);
        }
    }

    // fill the table
    this->transmissionTable.clear();
    for (i = 0; i < energy.size(); ++i)
    {
        this->transmissionTable[energy[i]] = transmission[i];
    }
    this->name = name;
    this->comment = comment;
}

std::string TransmissionTable::getComment() const
{
    return this->comment;
}

std::string TransmissionTable::getName() const
{
    return this->name;
}

double TransmissionTable::getTransmission(const double & energy) const
{
    //typedef std::map<double, double>::const_iterator i_t;
    std::map<double, double>::const_iterator i1, i2;
    double x1, x2, factor;

    if (this->transmissionTable.size() < 1)
    {
        return 1.0;
    }

    if (energy <= 0.0)
    {
        return 1.0;
    }

    i2 = this->transmissionTable.upper_bound(energy);
    if (i2 == this->transmissionTable.end())
    {
        // return last value of the table
        // return (--i)->second;
        // or return 1 because we are dealing with a transmission?
        return 1.0;
    }
    i1 = this->transmissionTable.begin();
    if (energy < (i1->second))
    {
        // return first value of the table
        // return i->second;
        // or return 0 because we are dealing with a transmission?
        return 0.0;
    }
    i1 = i2;
    i1--;

    x1 = i1->first;
    x2 = i2->first;

    // perform a linear interpolation
    factor = (energy - x1) / (x2 - x1);
    return factor * (i2->second) + (1.0 - factor) * i1->second;
}

std::vector<double> TransmissionTable::getTransmission(const std::vector<double> & energy) const
{
    std::vector<double>::size_type n, i;
    std::vector<double> result;

    n = energy.size();
    result.resize(n);
    for (i = 0; i < n; ++i)
    {
        result[i] = this->getTransmission(energy[i]);
    }
    return result;
}

std::map<double, double> TransmissionTable::getTransmissionTable() const
{
    return this->transmissionTable;
}

} // namespace fisx
<|endoftext|>


<commit_before>#include "libcmm_irob.h"
#include "cmm_socket.h"
#include <errno.h>

/* Begin an IROB on a multi-socket.
 * Such IROBs have sender labels, receiver labels, and a thunk
 * associated, just as traditional multi-socket send operations do. */
irob_id_t begin_irob(mc_socket_t sock, int numdeps, const irob_id_t *deps,
                     u_long send_labels,
                     resume_handler_t fn, void *arg)
{
    return CMMSocket::lookup(sock)->mc_begin_irob(numdeps, deps,
                                                  send_labels,
                                                  fn, arg);
}

/* End an IROB, notifying the receiver that it is complete. */
int end_irob(irob_id_t id)
{
    return CMMSocket::lookup_by_irob(id)->mc_end_irob(id);
}

/* Sending operations for IROBs.  Since an irob_id implies a socket,
 * the socket argument is not required.
 * Recall that send operations within an IROB are guaranteed to be
 * received in their original order (see receiver API below). */
ssize_t irob_send(irob_id_t irob_id, const void *buf, size_t len, int flags)
{
    return CMMSocket::lookup_by_irob(irob_id)->mc_irob_send(irob_id,
                                                            buf, len, flags);
}

int irob_writev(irob_id_t irob_id, const struct iovec *vector, int count)
{
    return CMMSocket::lookup_by_irob(irob_id)->mc_irob_writev(irob_id,
                                                              vector, count);
}

ssize_t
cmm_write_with_deps(mc_socket_t sock, const void *buf, size_t len,
		    int numdeps, const irob_id_t *deps,
		    u_long send_labels, resume_handler_t fn, void *arg,
		    irob_id_t *irob_id)
{
    return cmm_send_with_deps(sock, buf, len, 0, numdeps, deps,
			      send_labels, fn, arg, irob_id);
}

ssize_t
cmm_send_with_deps(mc_socket_t sock, const void *buf, size_t len, int flags,
		   int numdeps, const irob_id_t *deps,
		   u_long send_labels, resume_handler_t fn, void *arg,
		   irob_id_t *irob_id)
{
    irob_id_t id = begin_irob(sock, numdeps, deps, send_labels, fn, arg);
    if (id < 0) {
	if (errno == EBADF) {
	    // this must not be a multisocket.  send it regular-style!
	    return cmm_send(sock, buf, len, flags, send_labels, fn, arg);
	} else {
	    // some other error; just return it
	    return id;
	}
    }

    ssize_t bytes_sent = irob_send(id, buf, len, flags);
    if (bytes_sent < 0) {
	return bytes_sent;
    }

    int rc = end_irob(id);
    if (rc < 0) {
	return rc;
    }

    *irob_id = id;
    return bytes_sent;
}

int
cmm_writev_with_deps(mc_socket_t sock, const struct iovec *vector, int count,
		     int numdeps, const irob_id_t *deps,
		     u_long send_labels, resume_handler_t fn, void *arg,
		     irob_id_t *irob_id)
{
    irob_id_t id = begin_irob(sock, numdeps, deps, send_labels, fn, arg);
    if (id < 0) {
	if (errno == EBADF) {
	    // this must not be a multisocket.  send it regular-style!
	    return cmm_writev(sock, vector, count, send_labels, fn, arg);
	} else {
	    // some other error; just return it
	    return id;
	}
    }

    int bytes_sent = irob_writev(id, vector, count);
    if (bytes_sent < 0) {
	return bytes_sent;
    }

    int rc = end_irob(id);
    if (rc < 0) {
	return rc;
    }

    *irob_id = id;
    return bytes_sent;
}

int
irob_relabel(irob_id_t irob_id, u_long new_labels)
{
    return CMMSocket::lookup_by_irob(irob_id)->irob_relabel(irob_id, new_labels);
}
<commit_msg>Silly NULL-pointer dereference bug, fixed.<commit_after>#include "libcmm_irob.h"
#include "cmm_socket.h"
#include <errno.h>

/* Begin an IROB on a multi-socket.
 * Such IROBs have sender labels, receiver labels, and a thunk
 * associated, just as traditional multi-socket send operations do. */
irob_id_t begin_irob(mc_socket_t sock, int numdeps, const irob_id_t *deps,
                     u_long send_labels,
                     resume_handler_t fn, void *arg)
{
    return CMMSocket::lookup(sock)->mc_begin_irob(numdeps, deps,
                                                  send_labels,
                                                  fn, arg);
}

/* End an IROB, notifying the receiver that it is complete. */
int end_irob(irob_id_t id)
{
    return CMMSocket::lookup_by_irob(id)->mc_end_irob(id);
}

/* Sending operations for IROBs.  Since an irob_id implies a socket,
 * the socket argument is not required.
 * Recall that send operations within an IROB are guaranteed to be
 * received in their original order (see receiver API below). */
ssize_t irob_send(irob_id_t irob_id, const void *buf, size_t len, int flags)
{
    return CMMSocket::lookup_by_irob(irob_id)->mc_irob_send(irob_id,
                                                            buf, len, flags);
}

int irob_writev(irob_id_t irob_id, const struct iovec *vector, int count)
{
    return CMMSocket::lookup_by_irob(irob_id)->mc_irob_writev(irob_id,
                                                              vector, count);
}

ssize_t
cmm_write_with_deps(mc_socket_t sock, const void *buf, size_t len,
		    int numdeps, const irob_id_t *deps,
		    u_long send_labels, resume_handler_t fn, void *arg,
		    irob_id_t *irob_id)
{
    return cmm_send_with_deps(sock, buf, len, 0, numdeps, deps,
			      send_labels, fn, arg, irob_id);
}

ssize_t
cmm_send_with_deps(mc_socket_t sock, const void *buf, size_t len, int flags,
		   int numdeps, const irob_id_t *deps,
		   u_long send_labels, resume_handler_t fn, void *arg,
		   irob_id_t *irob_id)
{
    irob_id_t id = begin_irob(sock, numdeps, deps, send_labels, fn, arg);
    if (id < 0) {
	if (errno == EBADF) {
	    // this must not be a multisocket.  send it regular-style!
	    return cmm_send(sock, buf, len, flags, send_labels, fn, arg);
	} else {
	    // some other error; just return it
	    return id;
	}
    }

    ssize_t bytes_sent = irob_send(id, buf, len, flags);
    if (bytes_sent < 0) {
	return bytes_sent;
    }

    int rc = end_irob(id);
    if (rc < 0) {
	return rc;
    }

    if (irob_id) {
        *irob_id = id;
    }
    return bytes_sent;
}

int
cmm_writev_with_deps(mc_socket_t sock, const struct iovec *vector, int count,
		     int numdeps, const irob_id_t *deps,
		     u_long send_labels, resume_handler_t fn, void *arg,
		     irob_id_t *irob_id)
{
    irob_id_t id = begin_irob(sock, numdeps, deps, send_labels, fn, arg);
    if (id < 0) {
	if (errno == EBADF) {
	    // this must not be a multisocket.  send it regular-style!
	    return cmm_writev(sock, vector, count, send_labels, fn, arg);
	} else {
	    // some other error; just return it
	    return id;
	}
    }

    int bytes_sent = irob_writev(id, vector, count);
    if (bytes_sent < 0) {
	return bytes_sent;
    }

    int rc = end_irob(id);
    if (rc < 0) {
	return rc;
    }

    if (irob_id) {
        *irob_id = id;
    }
    return bytes_sent;
}

int
irob_relabel(irob_id_t irob_id, u_long new_labels)
{
    return CMMSocket::lookup_by_irob(irob_id)->irob_relabel(irob_id, new_labels);
}
<|endoftext|>


<commit_before>//===- Support/Chrono.cpp - Utilities for Timing Manipulation ---*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/Chrono.h"
#include "llvm/Config/config.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"

namespace llvm {

using namespace sys;

const char llvm::detail::unit<std::ratio<3600>>::value[] = "h";
const char llvm::detail::unit<std::ratio<60>>::value[] = "m";
const char llvm::detail::unit<std::ratio<1>>::value[] = "s";
const char llvm::detail::unit<std::milli>::value[] = "ms";
const char llvm::detail::unit<std::micro>::value[] = "us";
const char llvm::detail::unit<std::nano>::value[] = "ns";

static inline struct tm getStructTM(TimePoint<> TP) {
  struct tm Storage;
  std::time_t OurTime = toTimeT(TP);

#if defined(LLVM_ON_UNIX)
  struct tm *LT = ::localtime_r(&OurTime, &Storage);
  assert(LT);
  (void)LT;
#endif
#if defined(LLVM_ON_WIN32)
  int Error = ::localtime_s(&Storage, &OurTime);
  assert(!Error);
  (void)Error;
#endif

  return Storage;
}

raw_ostream &operator<<(raw_ostream &OS, TimePoint<> TP) {
  struct tm LT = getStructTM(TP);
  char Buffer[sizeof("YYYY-MM-DD HH:MM:SS")];
  strftime(Buffer, sizeof(Buffer), "%Y-%m-%d %H:%M:%S", &LT);
  return OS << Buffer << '.'
            << format("%.9lu",
                      long((TP.time_since_epoch() % std::chrono::seconds(1))
                               .count()));
}

void format_provider<TimePoint<>>::format(const TimePoint<> &T, raw_ostream &OS,
                                          StringRef Style) {
  using namespace std::chrono;
  TimePoint<seconds> Truncated = time_point_cast<seconds>(T);
  auto Fractional = T - Truncated;
  struct tm LT = getStructTM(Truncated);
  // Handle extensions first. strftime mangles unknown %x on some platforms.
  if (Style.empty()) Style = "%Y-%m-%d %H:%M:%S.%N";
  std::string Format;
  raw_string_ostream FStream(Format);
  for (unsigned I = 0; I < Style.size(); ++I) {
    if (Style[I] == '%' && Style.size() > I + 1) switch (Style[I + 1]) {
        case 'L':  // Milliseconds, from Ruby.
          FStream << llvm::format(
              "%.3lu", duration_cast<milliseconds>(Fractional).count());
          ++I;
          continue;
        case 'f':  // Microseconds, from Python.
          FStream << llvm::format(
              "%.6lu", duration_cast<microseconds>(Fractional).count());
          ++I;
          continue;
        case 'N':  // Nanoseconds, from date(1).
          FStream << llvm::format(
              "%.6lu", duration_cast<nanoseconds>(Fractional).count());
          ++I;
          continue;
        case '%':  // Consume %%, so %%f parses as (%%)f not %(%f)
          FStream << "%%";
          ++I;
          continue;
      }
    FStream << Style[I];
  }
  FStream.flush();
  char Buffer[256];  // Should be enough for anywhen.
  size_t Len = strftime(Buffer, sizeof(Buffer), Format.c_str(), &LT);
  OS << (Len ? Buffer : "BAD-DATE-FORMAT");
}

} // namespace llvm
<commit_msg>[Support][Chrono] Use explicit cast of text output of time values.<commit_after>//===- Support/Chrono.cpp - Utilities for Timing Manipulation ---*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/Chrono.h"
#include "llvm/Config/config.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"

namespace llvm {

using namespace sys;

const char llvm::detail::unit<std::ratio<3600>>::value[] = "h";
const char llvm::detail::unit<std::ratio<60>>::value[] = "m";
const char llvm::detail::unit<std::ratio<1>>::value[] = "s";
const char llvm::detail::unit<std::milli>::value[] = "ms";
const char llvm::detail::unit<std::micro>::value[] = "us";
const char llvm::detail::unit<std::nano>::value[] = "ns";

static inline struct tm getStructTM(TimePoint<> TP) {
  struct tm Storage;
  std::time_t OurTime = toTimeT(TP);

#if defined(LLVM_ON_UNIX)
  struct tm *LT = ::localtime_r(&OurTime, &Storage);
  assert(LT);
  (void)LT;
#endif
#if defined(LLVM_ON_WIN32)
  int Error = ::localtime_s(&Storage, &OurTime);
  assert(!Error);
  (void)Error;
#endif

  return Storage;
}

raw_ostream &operator<<(raw_ostream &OS, TimePoint<> TP) {
  struct tm LT = getStructTM(TP);
  char Buffer[sizeof("YYYY-MM-DD HH:MM:SS")];
  strftime(Buffer, sizeof(Buffer), "%Y-%m-%d %H:%M:%S", &LT);
  return OS << Buffer << '.'
            << format("%.9lu",
                      long((TP.time_since_epoch() % std::chrono::seconds(1))
                               .count()));
}

void format_provider<TimePoint<>>::format(const TimePoint<> &T, raw_ostream &OS,
                                          StringRef Style) {
  using namespace std::chrono;
  TimePoint<seconds> Truncated = time_point_cast<seconds>(T);
  auto Fractional = T - Truncated;
  struct tm LT = getStructTM(Truncated);
  // Handle extensions first. strftime mangles unknown %x on some platforms.
  if (Style.empty()) Style = "%Y-%m-%d %H:%M:%S.%N";
  std::string Format;
  raw_string_ostream FStream(Format);
  for (unsigned I = 0; I < Style.size(); ++I) {
    if (Style[I] == '%' && Style.size() > I + 1) switch (Style[I + 1]) {
        case 'L':  // Milliseconds, from Ruby.
          FStream << llvm::format(
              "%.3lu", (long)duration_cast<milliseconds>(Fractional).count());
          ++I;
          continue;
        case 'f':  // Microseconds, from Python.
          FStream << llvm::format(
              "%.6lu", (long)duration_cast<microseconds>(Fractional).count());
          ++I;
          continue;
        case 'N':  // Nanoseconds, from date(1).
          FStream << llvm::format(
              "%.6lu", (long)duration_cast<nanoseconds>(Fractional).count());
          ++I;
          continue;
        case '%':  // Consume %%, so %%f parses as (%%)f not %(%f)
          FStream << "%%";
          ++I;
          continue;
      }
    FStream << Style[I];
  }
  FStream.flush();
  char Buffer[256];  // Should be enough for anywhen.
  size_t Len = strftime(Buffer, sizeof(Buffer), Format.c_str(), &LT);
  OS << (Len ? Buffer : "BAD-DATE-FORMAT");
}

} // namespace llvm
<|endoftext|>


<commit_before>#ifdef _WIN32
//	request += "Connection: Keep-Alive\n";
#include <ws2tcpip.h>
#include <windows.h>
#include <winhttp.h>
#pragma comment(lib, "Winhttp.lib")
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#define INVALID_SOCKET -1
#include <unistd.h>
#endif

#include "http.h"
#include "libuuu.h"
#include "liberror.h"
#include <string.h>
#include <locale>
#include <codecvt>

#ifdef UUUSSL
#include <openssl/ssl.h>
#include <openssl/err.h>

class CUUUSSL
{
public:
	CUUUSSL()
	{
#if OPENSSL_VERSION_NUMBER < 0x10100000L
		SSL_library_init();
		SSLeay_add_ssl_algorithms();
		SSL_load_error_strings();
#else
		OPENSSL_init_ssl(0, NULL);
		SSLeay_add_ssl_algorithms();
#endif
	}
	~CUUUSSL()
	{
	}
};

static CUUUSSL g_uuussl;

#endif

using namespace std;

#ifdef _WIN32
/* Win32 implement*/

HttpStream::HttpStream()
{
	m_buff.empty();
	m_socket = 0;
	m_hConnect = 0;
	m_hSession = 0;
	m_hRequest = 0;
}

int HttpStream::HttpGetHeader(std::string host, std::string path, int port)
{

	m_hSession = WinHttpOpen(L"WinHTTP UUU/1.0",
		WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
		WINHTTP_NO_PROXY_NAME,
		WINHTTP_NO_PROXY_BYPASS, 0);

	if (!m_hSession)
	{
		set_last_err_string("fail WinHttpOpen");
		return -1;
	}

	wstring_convert<codecvt_utf8_utf16<wchar_t>> converter;
	wstring whost = converter.from_bytes(host);

	if (m_hSession)
		m_hConnect = WinHttpConnect(m_hSession, whost.c_str(),
			port, 0);

	if (!m_hConnect)
	{
		set_last_err_string("Fail Connection");
		return -1;
	}

	wstring wpath = converter.from_bytes(path);

	m_hRequest = WinHttpOpenRequest(m_hConnect, L"GET", wpath.c_str(),
			NULL, WINHTTP_NO_REFERER,
			WINHTTP_DEFAULT_ACCEPT_TYPES,
			port==443?WINHTTP_FLAG_SECURE:0);

	BOOL  bResults = FALSE;
	if (!m_hRequest)
	{
		set_last_err_string("Fail WinHttpOpenRequest");
		return -1;
	}

	bResults = WinHttpSendRequest(m_hRequest,
			WINHTTP_NO_ADDITIONAL_HEADERS, 0,
			WINHTTP_NO_REQUEST_DATA, 0,
			0, 0);

	if (!bResults)
	{
		set_last_err_string("Fail WinHttpSendRequest");
		return -1;
	}

	bResults = WinHttpReceiveResponse(m_hRequest, NULL);

	if (!bResults)
	{
		set_last_err_string("Fail WinHttpReceiveResponse");
		return -1;
	}

	DWORD status = 0;
	DWORD dwSize = sizeof(status);
	WinHttpQueryHeaders(m_hRequest, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
		WINHTTP_HEADER_NAME_BY_INDEX, &status,
		&dwSize, WINHTTP_NO_HEADER_INDEX);

	if (status != HTTP_STATUS_OK)
	{
		set_last_err_string("HTTP status is not okay");
		return -1;
	}
	return 0;
}

size_t HttpStream::HttpGetFileSize()
{
	DWORD dwSize = 0;
	BOOL  bResults = FALSE;
	wstring out;

	WinHttpQueryHeaders(m_hRequest, WINHTTP_QUERY_CONTENT_LENGTH,
		WINHTTP_HEADER_NAME_BY_INDEX, NULL,
		&dwSize, WINHTTP_NO_HEADER_INDEX);

	// Allocate memory for the buffer.
	if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
	{
		out.resize(dwSize / sizeof(WCHAR));

		// Now, use WinHttpQueryHeaders to retrieve the header.
		bResults = WinHttpQueryHeaders(m_hRequest,
			WINHTTP_QUERY_CONTENT_LENGTH,
			WINHTTP_HEADER_NAME_BY_INDEX,
			(LPVOID)out.c_str(), &dwSize,
			WINHTTP_NO_HEADER_INDEX);
	}
	return _wtoll(out.c_str());
}

int HttpStream::HttpDownload(char *buff, size_t sz)
{
	DWORD dwSize = 0;
	DWORD dwDownloaded = 0;
	while (sz)
	{
		if (!WinHttpQueryDataAvailable(m_hRequest, &dwSize))
		{
			set_last_err_string("WinHttpQueryDataAvailable");
			return -1;
		}

		if (dwSize > sz)
			dwSize = sz;

		if (!WinHttpReadData(m_hRequest, (LPVOID)buff,
			dwSize, &dwDownloaded))
		{
			set_last_err_string("Fail at WinHttpReadData");
			return -1;
		}
		buff += dwDownloaded;
		sz -= dwDownloaded;
	}
	return 0;
}

HttpStream::~HttpStream()
{
	if (m_hRequest)
		WinHttpCloseHandle(m_hRequest);
	if (m_hConnect)
		WinHttpCloseHandle(m_hConnect);
	if (m_hSession)
		WinHttpCloseHandle(m_hSession);
}

#else

HttpStream::HttpStream()
{
	m_buff.empty();
	m_ssl = NULL;
}

int HttpStream::SendPacket(char *buff, size_t sz)
{
#ifdef UUUSSL
	if(m_ssl)
		return SSL_write((SSL*)m_ssl, buff, sz);
#endif
	return send(m_socket, buff, sz, 0);
}

int HttpStream::RecvPacket(char *buff, size_t sz)
{
#ifdef UUUSSL
	if(m_ssl)
		return SSL_read((SSL*)m_ssl, buff, sz);
#endif
	return recv(m_socket, buff, sz, 0);
}

int HttpStream::HttpGetHeader(std::string host, std::string path, int port)
{
	int ret;
	addrinfo *pAddrInfo;
	char s_port[10];
	snprintf(s_port, 10, "%d", port);

	if (getaddrinfo(host.c_str(), s_port, 0, &pAddrInfo))
	{
		set_last_err_string("get network address error");
		return -1;
	}

	m_socket = socket(pAddrInfo->ai_family, pAddrInfo->ai_socktype, pAddrInfo->ai_protocol);

	struct timeval tv;
	tv.tv_sec = 10;
	tv.tv_usec = 0;

	setsockopt(m_socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv));

	if (m_socket == INVALID_SOCKET)
	{
		set_last_err_string("Can't get sock");
		return -1;
	}

	if (connect(m_socket, pAddrInfo->ai_addr, pAddrInfo->ai_addrlen))
	{
		set_last_err_string("connect error");
		return -1;
	}

	if(port == 443)
	{
#ifdef UUUSSL

		const SSL_METHOD *meth = TLSv1_2_client_method();
		if(!meth)
		{
			set_last_err_string("Failure at TLSv1_2_client_method\n");
			return -1;
		}
		SSL_CTX *ctx = SSL_CTX_new (meth);
		if(!ctx)
		{
			set_last_err_string("Error create ssl ctx\n");
			return -1;
		}
		m_ssl = SSL_new (ctx);
		if(!m_ssl)
		{
			set_last_err_string("Error create SSL\n");
			return -1;
		}
		SSL_set_fd((SSL*)m_ssl, m_socket);
		if( SSL_connect((SSL*)m_ssl) <= 0)
		{
			set_last_err_string("error build ssl connection");
			return -1;
		}
#else
		set_last_err_string("Can't support https");
		return -1;
#endif
        }

	if(port == 443)
		path = "https://" + host + path;

	string request = "GET " + path + " HTTP/1.1\r\n";
	request += "Host: " + host + "\r\n\r\n";

	ret = SendPacket((char*)request.c_str(), request.size());
	if (ret != request.size())
	{
		set_last_err_string("http send error");
		return -1;
	}

	m_buff.resize(1024);
	ret = RecvPacket((char*)m_buff.data(), m_buff.size());
	if (ret < 0)
	{
		set_last_err_string("http recv Error");
		return -1;
	}

	int i;
	for (i = 0; i < 1024 - 4; i++)
	{
		if (m_buff[i] == 0xd &&
			m_buff[i + 1] == 0xa &&
			m_buff[i + 2] == 0xd &&
			m_buff[i + 3] == 0xa)
		{
			break;
		}
	}

	if (i >= 1024 - 4)
	{
		set_last_err_string("Can't find termaniate");
		return -1;
	}

	m_data_start = i + 4;

	string str;
	str.resize(i + 2);
	memcpy((void*)str.c_str(), m_buff.data(), i + 2);

	if (parser_response(str))
		return -1;

	return 0;
}

size_t HttpStream::HttpGetFileSize()
{
	return atoll(m_response["Content-Length"].c_str());
}

int HttpStream::parser_response(string rep)
{
	size_t pos = rep.find("\r\n");
	if (pos == string::npos)
	{
		set_last_err_string("Can't find \r\n");
		return -1;
	}

	string str = rep.substr(0, pos);
	if (str != "HTTP/1.1 200 OK")
	{
		set_last_err_string(str);
		return -1;
	}

	m_response.clear();

	while (pos != string::npos)
	{
		pos += 2;
		size_t split = rep.find(':', pos);
		if (split == string::npos)
			break;
		string key = rep.substr(pos, split - pos);
		pos = rep.find("\r\n", pos);
		string value = rep.substr(split + 1, pos - split - 1);
		m_response[key] = value;
	}

	return 0;
}

int HttpStream::HttpDownload(char *buff, size_t sz)
{
	size_t left = 0;
	if (m_data_start < m_buff.size())
		left = m_buff.size() - m_data_start;

	size_t trim_transfered = 0;

	if (left)
	{

		trim_transfered = sz;
		if (trim_transfered > left)
			trim_transfered = left;

		memcpy(buff, m_buff.data() + m_data_start, trim_transfered);
		m_data_start += trim_transfered;
	}

	if (trim_transfered < sz)
	{
		int ret = 0;
		sz -= trim_transfered;
		buff += trim_transfered;
		while (sz && ((ret = RecvPacket(buff, sz)) > 0))
		{
			buff += ret;
			sz -= ret;
		}

		if (ret < 0)
		{
			set_last_err_string("recv error");
			return -1;
		}
	}

	return 0;
}

HttpStream::~HttpStream()
{
	close(m_socket);
#ifdef UUUSSL
	if(m_ssl)
	{
		SSL_CTX_free(SSL_get_SSL_CTX((SSL*)m_ssl));
		SSL_free((SSL*)m_ssl);
	}
#endif
}

#endif
<commit_msg>add missed copyright for http.cpp<commit_after>/*
 * Copyright 2019 NXP.
 *
 * 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 the NXP Semiconductor 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 HOLDER 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.
 *
 */

#ifdef _WIN32
//	request += "Connection: Keep-Alive\n";
#include <ws2tcpip.h>
#include <windows.h>
#include <winhttp.h>
#pragma comment(lib, "Winhttp.lib")
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#define INVALID_SOCKET -1
#include <unistd.h>
#endif

#include "http.h"
#include "libuuu.h"
#include "liberror.h"
#include <string.h>
#include <locale>
#include <codecvt>

#ifdef UUUSSL
#include <openssl/ssl.h>
#include <openssl/err.h>

class CUUUSSL
{
public:
	CUUUSSL()
	{
#if OPENSSL_VERSION_NUMBER < 0x10100000L
		SSL_library_init();
		SSLeay_add_ssl_algorithms();
		SSL_load_error_strings();
#else
		OPENSSL_init_ssl(0, NULL);
		SSLeay_add_ssl_algorithms();
#endif
	}
	~CUUUSSL()
	{
	}
};

static CUUUSSL g_uuussl;

#endif

using namespace std;

#ifdef _WIN32
/* Win32 implement*/

HttpStream::HttpStream()
{
	m_buff.empty();
	m_socket = 0;
	m_hConnect = 0;
	m_hSession = 0;
	m_hRequest = 0;
}

int HttpStream::HttpGetHeader(std::string host, std::string path, int port)
{

	m_hSession = WinHttpOpen(L"WinHTTP UUU/1.0",
		WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
		WINHTTP_NO_PROXY_NAME,
		WINHTTP_NO_PROXY_BYPASS, 0);

	if (!m_hSession)
	{
		set_last_err_string("fail WinHttpOpen");
		return -1;
	}

	wstring_convert<codecvt_utf8_utf16<wchar_t>> converter;
	wstring whost = converter.from_bytes(host);

	if (m_hSession)
		m_hConnect = WinHttpConnect(m_hSession, whost.c_str(),
			port, 0);

	if (!m_hConnect)
	{
		set_last_err_string("Fail Connection");
		return -1;
	}

	wstring wpath = converter.from_bytes(path);

	m_hRequest = WinHttpOpenRequest(m_hConnect, L"GET", wpath.c_str(),
			NULL, WINHTTP_NO_REFERER,
			WINHTTP_DEFAULT_ACCEPT_TYPES,
			port==443?WINHTTP_FLAG_SECURE:0);

	BOOL  bResults = FALSE;
	if (!m_hRequest)
	{
		set_last_err_string("Fail WinHttpOpenRequest");
		return -1;
	}

	bResults = WinHttpSendRequest(m_hRequest,
			WINHTTP_NO_ADDITIONAL_HEADERS, 0,
			WINHTTP_NO_REQUEST_DATA, 0,
			0, 0);

	if (!bResults)
	{
		set_last_err_string("Fail WinHttpSendRequest");
		return -1;
	}

	bResults = WinHttpReceiveResponse(m_hRequest, NULL);

	if (!bResults)
	{
		set_last_err_string("Fail WinHttpReceiveResponse");
		return -1;
	}

	DWORD status = 0;
	DWORD dwSize = sizeof(status);
	WinHttpQueryHeaders(m_hRequest, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
		WINHTTP_HEADER_NAME_BY_INDEX, &status,
		&dwSize, WINHTTP_NO_HEADER_INDEX);

	if (status != HTTP_STATUS_OK)
	{
		set_last_err_string("HTTP status is not okay");
		return -1;
	}
	return 0;
}

size_t HttpStream::HttpGetFileSize()
{
	DWORD dwSize = 0;
	BOOL  bResults = FALSE;
	wstring out;

	WinHttpQueryHeaders(m_hRequest, WINHTTP_QUERY_CONTENT_LENGTH,
		WINHTTP_HEADER_NAME_BY_INDEX, NULL,
		&dwSize, WINHTTP_NO_HEADER_INDEX);

	// Allocate memory for the buffer.
	if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
	{
		out.resize(dwSize / sizeof(WCHAR));

		// Now, use WinHttpQueryHeaders to retrieve the header.
		bResults = WinHttpQueryHeaders(m_hRequest,
			WINHTTP_QUERY_CONTENT_LENGTH,
			WINHTTP_HEADER_NAME_BY_INDEX,
			(LPVOID)out.c_str(), &dwSize,
			WINHTTP_NO_HEADER_INDEX);
	}
	return _wtoll(out.c_str());
}

int HttpStream::HttpDownload(char *buff, size_t sz)
{
	DWORD dwSize = 0;
	DWORD dwDownloaded = 0;
	while (sz)
	{
		if (!WinHttpQueryDataAvailable(m_hRequest, &dwSize))
		{
			set_last_err_string("WinHttpQueryDataAvailable");
			return -1;
		}

		if (dwSize > sz)
			dwSize = sz;

		if (!WinHttpReadData(m_hRequest, (LPVOID)buff,
			dwSize, &dwDownloaded))
		{
			set_last_err_string("Fail at WinHttpReadData");
			return -1;
		}
		buff += dwDownloaded;
		sz -= dwDownloaded;
	}
	return 0;
}

HttpStream::~HttpStream()
{
	if (m_hRequest)
		WinHttpCloseHandle(m_hRequest);
	if (m_hConnect)
		WinHttpCloseHandle(m_hConnect);
	if (m_hSession)
		WinHttpCloseHandle(m_hSession);
}

#else

HttpStream::HttpStream()
{
	m_buff.empty();
	m_ssl = NULL;
}

int HttpStream::SendPacket(char *buff, size_t sz)
{
#ifdef UUUSSL
	if(m_ssl)
		return SSL_write((SSL*)m_ssl, buff, sz);
#endif
	return send(m_socket, buff, sz, 0);
}

int HttpStream::RecvPacket(char *buff, size_t sz)
{
#ifdef UUUSSL
	if(m_ssl)
		return SSL_read((SSL*)m_ssl, buff, sz);
#endif
	return recv(m_socket, buff, sz, 0);
}

int HttpStream::HttpGetHeader(std::string host, std::string path, int port)
{
	int ret;
	addrinfo *pAddrInfo;
	char s_port[10];
	snprintf(s_port, 10, "%d", port);

	if (getaddrinfo(host.c_str(), s_port, 0, &pAddrInfo))
	{
		set_last_err_string("get network address error");
		return -1;
	}

	m_socket = socket(pAddrInfo->ai_family, pAddrInfo->ai_socktype, pAddrInfo->ai_protocol);

	struct timeval tv;
	tv.tv_sec = 10;
	tv.tv_usec = 0;

	setsockopt(m_socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv));

	if (m_socket == INVALID_SOCKET)
	{
		set_last_err_string("Can't get sock");
		return -1;
	}

	if (connect(m_socket, pAddrInfo->ai_addr, pAddrInfo->ai_addrlen))
	{
		set_last_err_string("connect error");
		return -1;
	}

	if(port == 443)
	{
#ifdef UUUSSL

		const SSL_METHOD *meth = TLSv1_2_client_method();
		if(!meth)
		{
			set_last_err_string("Failure at TLSv1_2_client_method\n");
			return -1;
		}
		SSL_CTX *ctx = SSL_CTX_new (meth);
		if(!ctx)
		{
			set_last_err_string("Error create ssl ctx\n");
			return -1;
		}
		m_ssl = SSL_new (ctx);
		if(!m_ssl)
		{
			set_last_err_string("Error create SSL\n");
			return -1;
		}
		SSL_set_fd((SSL*)m_ssl, m_socket);
		if( SSL_connect((SSL*)m_ssl) <= 0)
		{
			set_last_err_string("error build ssl connection");
			return -1;
		}
#else
		set_last_err_string("Can't support https");
		return -1;
#endif
        }

	if(port == 443)
		path = "https://" + host + path;

	string request = "GET " + path + " HTTP/1.1\r\n";
	request += "Host: " + host + "\r\n\r\n";

	ret = SendPacket((char*)request.c_str(), request.size());
	if (ret != request.size())
	{
		set_last_err_string("http send error");
		return -1;
	}

	m_buff.resize(1024);
	ret = RecvPacket((char*)m_buff.data(), m_buff.size());
	if (ret < 0)
	{
		set_last_err_string("http recv Error");
		return -1;
	}

	int i;
	for (i = 0; i < 1024 - 4; i++)
	{
		if (m_buff[i] == 0xd &&
			m_buff[i + 1] == 0xa &&
			m_buff[i + 2] == 0xd &&
			m_buff[i + 3] == 0xa)
		{
			break;
		}
	}

	if (i >= 1024 - 4)
	{
		set_last_err_string("Can't find termaniate");
		return -1;
	}

	m_data_start = i + 4;

	string str;
	str.resize(i + 2);
	memcpy((void*)str.c_str(), m_buff.data(), i + 2);

	if (parser_response(str))
		return -1;

	return 0;
}

size_t HttpStream::HttpGetFileSize()
{
	return atoll(m_response["Content-Length"].c_str());
}

int HttpStream::parser_response(string rep)
{
	size_t pos = rep.find("\r\n");
	if (pos == string::npos)
	{
		set_last_err_string("Can't find \r\n");
		return -1;
	}

	string str = rep.substr(0, pos);
	if (str != "HTTP/1.1 200 OK")
	{
		set_last_err_string(str);
		return -1;
	}

	m_response.clear();

	while (pos != string::npos)
	{
		pos += 2;
		size_t split = rep.find(':', pos);
		if (split == string::npos)
			break;
		string key = rep.substr(pos, split - pos);
		pos = rep.find("\r\n", pos);
		string value = rep.substr(split + 1, pos - split - 1);
		m_response[key] = value;
	}

	return 0;
}

int HttpStream::HttpDownload(char *buff, size_t sz)
{
	size_t left = 0;
	if (m_data_start < m_buff.size())
		left = m_buff.size() - m_data_start;

	size_t trim_transfered = 0;

	if (left)
	{

		trim_transfered = sz;
		if (trim_transfered > left)
			trim_transfered = left;

		memcpy(buff, m_buff.data() + m_data_start, trim_transfered);
		m_data_start += trim_transfered;
	}

	if (trim_transfered < sz)
	{
		int ret = 0;
		sz -= trim_transfered;
		buff += trim_transfered;
		while (sz && ((ret = RecvPacket(buff, sz)) > 0))
		{
			buff += ret;
			sz -= ret;
		}

		if (ret < 0)
		{
			set_last_err_string("recv error");
			return -1;
		}
	}

	return 0;
}

HttpStream::~HttpStream()
{
	close(m_socket);
#ifdef UUUSSL
	if(m_ssl)
	{
		SSL_CTX_free(SSL_get_SSL_CTX((SSL*)m_ssl));
		SSL_free((SSL*)m_ssl);
	}
#endif
}

#endif
<|endoftext|>


<commit_before>#include "./qimage_drawer.h"
#include <QPainter>
#include <vector>

namespace Graphics
{

QImageDrawer::QImageDrawer(int width, int height)
{
  image = std::make_shared<QImage>(width, height, QImage::Format_Grayscale8);
}

void drawPolygon(QPainter &painter, std::vector<QPointF> &points)
{
  if (points.size() < 3)
    return;

  QPointF triangle[3];
  triangle[0] = points[0];
  for (size_t i = 2; i < points.size(); ++i)
  {
    triangle[1] = points[i - 1];
    triangle[2] = points[i];
    painter.drawConvexPolygon(triangle, 3);
  }
  points.clear();
}

void QImageDrawer::drawElementVector(std::vector<float> positions, float color)
{
  QPainter painter;
  painter.begin(image.get());
  QColor brushColor = QColor::fromRgbF(color, color, color, 1.0f);
  painter.setBrush(QBrush(brushColor));
  painter.setPen(brushColor);

  std::vector<QPointF> points;
  size_t i = 0;
  if (positions[0] == positions[2] && positions[1] == positions[3])
    i = 1;

  for (; i < positions.size() / 2; ++i)
  {
    float x = positions[i * 2];
    float y = image->height() - positions[i * 2 + 1];
    if (i * 2 + 3 < positions.size() && x == positions[i * 2 + 2] &&
        y == positions[i * 2 + 3])
    {
      drawPolygon(painter, points);
      points.clear();
      i += 2;
    }
    points.push_back(QPointF(x, y));
  }
  drawPolygon(painter, points);
  painter.end();
}

void QImageDrawer::clear()
{
  image->fill(Qt::GlobalColor::black);
}

}  // namespace Graphics
<commit_msg>Implement drawing with logical or in QImageDrawer.<commit_after>#include "./qimage_drawer.h"
#include <QPainter>
#include <vector>

namespace Graphics
{

QImageDrawer::QImageDrawer(int width, int height)
{
  image = std::make_shared<QImage>(width, height, QImage::Format_Grayscale8);
}

void drawPolygon(QPainter &painter, std::vector<QPointF> &points)
{
  if (points.size() < 3)
    return;

  QPointF triangle[3];
  triangle[0] = points[0];
  for (size_t i = 2; i < points.size(); ++i)
  {
    triangle[1] = points[i - 1];
    triangle[2] = points[i];
    painter.drawConvexPolygon(triangle, 3);
  }
  points.clear();
}

void QImageDrawer::drawElementVector(std::vector<float> positions, float color)
{
  QPainter painter;
  QImage tempImage(image->width(), image->height(), image->format());
  tempImage.fill(Qt::GlobalColor::black);
  painter.begin(&tempImage);
  QColor brushColor = QColor::fromRgbF(color, color, color, 1.0f);
  painter.setBrush(QBrush(brushColor));
  painter.setPen(brushColor);

  std::vector<QPointF> points;
  size_t i = 0;
  if (positions[0] == positions[2] && positions[1] == positions[3])
    i = 1;

  for (; i < positions.size() / 2; ++i)
  {
    float x = positions[i * 2];
    float y = image->height() - positions[i * 2 + 1];
    if (i * 2 + 3 < positions.size() && x == positions[i * 2 + 2] &&
        y == positions[i * 2 + 3])
    {
      drawPolygon(painter, points);
      points.clear();
      i += 2;
    }
    points.push_back(QPointF(x, y));
  }
  drawPolygon(painter, points);
  painter.end();

  for (int x = 0; x < image->width(); ++x)
  {
    for (int y = 0; y < image->height(); ++y)
    {
      QRgb imagePixel = image->pixel(x, y);
      QRgb tempPixel = tempImage.pixel(x, y);
      image->setPixel(x, y, imagePixel | tempPixel);
    }
  }
}

void QImageDrawer::clear()
{
  image->fill(Qt::GlobalColor::black);
}

}  // namespace Graphics
<|endoftext|>